package auth

import (
	"context"
	"encoding/json"
	"github.com/zeromicro/go-zero/core/collection"
	"github.com/zeromicro/go-zero/core/logx"
	"go.uber.org/zap"
	"navi-mumbai/app/api/admin/internal/model/pg"
	"strconv"
	"sync"
	"time"
)

type ApiPermission struct {
	sync.RWMutex
	permissionLevelMap      map[int64]int64 // api:level
	adminApiPermissionCache *collection.Cache
	ManagerModel            pg.ManagerModel
	logx.Logger
}

func newApiPermission(size int) *ApiPermission {
	sm := new(ApiPermission)
	sm.permissionLevelMap = make(map[int64]int64, size)
	sm.Logger = logx.WithDuration(time.Second)
	return sm
}

func (apm *ApiPermission) readApiPermissionLevelMap(api int64) int64 {
	apm.RLock()
	defer apm.RUnlock()
	value, ok := apm.permissionLevelMap[api]
	if ok {
		return value
	}
	return 0
}

func (apm *ApiPermission) writeApiPermissionLevelMap(api int64, value int64) {
	apm.Lock()
	defer apm.Unlock()
	apm.permissionLevelMap[api] = value
}

func (apm *ApiPermission) getApiPermissionLevelMapJsonStr() string {
	apm.RLock()
	defer apm.RUnlock()
	buf, err := json.Marshal(apm.permissionLevelMap)
	if err != nil {
		apm.Logger.Errorf("err == ", zap.Error(err))
		panic(err)
	}
	return string(buf)
}

func (apm *ApiPermission) setAdminApiPermission(uid int64, m map[int64]bool) {
	apm.adminApiPermissionCache.SetWithExpire(strconv.FormatInt(uid, 10), m, 0)
}

func (apm *ApiPermission) existAdminApiPermission(ctx context.Context, uid int64, api int64) bool {
	value, ok := apm.adminApiPermissionCache.Get(strconv.FormatInt(uid, 10))
	if ok {
		m := value.(map[int64]bool)
		_, ok = m[api]
		if ok {
			return true
		}
		return false
	}
	// 从数据库中获取
	mg, err := apm.ManagerModel.FindOne(ctx, uid)
	if err != nil {
		apm.Logger.Errorf("err == ", zap.Error(err))
		return false
	}
	if mg != nil {
		if mg.AllowApi == "" {
			return false
		}
		am := parseAllowApiMap(mg.AllowApi)
		if len(am) <= 0 {
			return false
		}
		apm.setAdminApiPermission(uid, am)
		_, ok = am[api]
		if ok {
			return true
		}
	}
	return false
}
